home *** CD-ROM | disk | FTP | other *** search
- include 386power.inc
- include 386video.inc
-
- ; BASIC VIDEO SERVICES
- ; _SetGameMode
- ; _RestoreTextMode
- ; _WaitVR
- ; _DisplayStart
- ; _PageFlip
-
- code32 segment para public use32
- assume cs:code32,ds:code32
-
- _ActiveBase dd 0 ;base of page to write to
- MidBase dd 0 ;base of "in between" page
- _ViewBase dd 0 ;base of page to show
- _ScoBase dd 0 ;base of "scoreboard" panel
-
- ; index of row start offsets from base of display screen (active,view,score)
- _RowStart dd 0
- dd VYHEIGHT dup(0)
-
- ; sottrai VGARAWOFFSET per passare da pointer code32 relativo
- ; ad offset nella vga memory window
- VGARAWOFFSET dd 0
-
- DispOffset dd 0 ; offset di scrolling
- ; old code for pix panning
- ; SmoothPix dd 0 ; valore per smooth scrolling
-
- ; XVGA MODE ENTRY/EXIT ROUTINES
-
- ;----------------------------------------------------------------------------
- ; void SetGameMode;
- ;
- public _SetGameMode
- _SetGameMode:
-
- pushad
-
-
- mov V86ax,0013h ; set 256-color mode BIOS MODE 13h
- mov al,10h ;
- int 33h ;
-
- mov dx,SEQUENCER ; convert to X-mode addressing
- ; sequencer register 04h (MEMORY MODE)
- ; set chain mode off,no odd/even,more than 64k,graphics mode
- mov ax,0604h ;
- out dx,ax ;
-
- WRITEMODE WPUT
- WRITEPLANE WPA
-
- @rlp edi,000A0000h
- mov ecx,16*1024 ; CLEAR VIDEO MEMORY
- xor eax,eax ; (addressing mode is planar
- rep stosd ; but raster scanning is still the
- ; same of mode 13h)
-
- ; now change the raster scanning method
- mov dx,CRTC
-
- mov ax,00014h ; TURN OFF DWORD MODE (CRTC LONG MODE)
- out dx,ax ; (change vram scanning method)
-
- mov ax,0E317h ; TURN ON BYTE MODE
- out dx,ax ;
-
- ; Tweaked mode fully activated, now perform other stuff
-
- mov al,LINE_OFS
- mov ah,SXWIDTH ; ampiezza di una linea/8
- out dx,ax
-
- ;mov dx,GRAPHICS ; superfluo se non sei paranoide
- ;mov ax,ALL_BIT
- ;out dx,ax
-
-
-
- ; inizializza variabili "interne" ed "esterne"
- @rlp eax,0A0000h
- mov VGARAWOFFSET,eax
- @rlp eax,SCOBASE
- mov _ScoBase,eax
- @rlp eax,BASE0
- mov _ViewBase,eax
- @rlp eax,BASE1
- mov MidBase,eax
- @rlp eax,BASE2
- mov _ActiveBase,eax
- ; xor eax,eax
- mov DispOffset,eax
- ; mov SmoothPix,eax
-
- mov edi,offset _RowStart ; Row offset table
- mov ecx,VYHEIGHT ;
- mov eax,0 ;
- mov ebx,PXWIDTH ;
-
- iloop:
- stosd
- add eax,ebx
- loop iloop
-
- mov ecx,LYHEIGHT
- call SplitScreen
- call InstallPFLP
- call _PageFlip
- ; ritorna a chi ha chiamato
- popad
- ret
-
- ;----------------------------------------------------------------------------
- ; void RestoreTextMode( void )
-
- public _RestoreTextMode
- _RestoreTextMode:
- mov V86ax,0003h ; set text mode
- mov al,10h
- int 33h
- ret
-
-
-
- ;----------------------------------------------------------------------------
- ; void _WaitVR(void) WAIT A FULL V.R TIME FRAME
- ;
-
- public _WaitVR
- _WaitVR: push edx
- push eax
- mov dx,STATUS
- @@swap_retr1: cli
- in al,dx
- test al,8 ; VERTICAL RETRACE ?
- jnz @@swap_retr1 ; loop if V.R. (into retrace)
- @@swap_retr2:
- in al,dx
- test al,8 ; V.R. ?
- jz @@swap_retr2 ; loop if not V.R.
- sti
- pop eax
- pop edx
- ; NOW you have a FULL V.R. time frame available
- ret
-
-
-
- ;----------------------------------------------------------------------------
- ; void DisplayStart(eax= x,edx =y) SET DISPLAY VIDEO WINDOW POSITION
- ; INSIDE DISPLAY PAGE
-
- public _DisplayStart
-
- _DisplayStart:
- ; eax= x_position , ebx = y_position
- ;;push ecx
- push eax
- ;;mov ecx,eax ;
- ;;and ecx,3 ; maschera di bits per lo shifter
- ;;shl ecx,1 ;
- ;;mov SmoothPix,ecx ;
-
- shr eax,2 ;offset nella pagina video corrente
- add eax,_RowStart[edx*4] ;
- mov DispOffset,eax ;
- pop eax
- ;;pop ecx
- ret
-
-
- ;----------------------------------------------------------------------------
- ; void DisplayPage(ECX= offset of display page )
- ; SHOW PAGE starting at offset eax (INTERNAL FUNCTION)
-
- DisplayPage:
- ; ecx = offset di inizio pagina video corrente
- mov bx,VSTART_HILO ;preload for fastest access
- add ecx,DispOffset ; somma l' inizio video nella pagina
- sub ecx,VGARAWOFFSET ; trasforma in raw vga offset
- xchg bh,cl ; BX=prima coppia CX=seconda coppia
-
- mov dx,STATUS
-
- cli
- ;@@WaitNVS:
- ; in al,dx
- ; and al,08h
- ; jnz @@WaitNVS ;vertical sync is active high (0= drawing)
- @@WaitHS:
- in al,dx
- and al,01
- jnz @@WaitHS ;hor. sync is active high (1 = active)
- ; n.b. HSync is display enable too!!!
-
- ; Set the start offset in display memory of the page to display.
- mov dx,CRTC
- mov eax,ebx
- out dx,ax ;start address low
- mov eax,ecx
- out dx,ax ;start address high
-
- ; mov dx,STATUS
- ;@@WaitVS:
- ; in al,dx
- ; and al,08h
- ; jz @@WaitVS ;vertical sync is active high (1 = active)
- ;@@QuickFlip:
- ; ; attribute controller already in address mode
- ; mov dx,ATTRIBUTE
- ; mov al,PEL_PANNING
- ; out dx,al
- ; mov al,byte ptr SmoothPix
- ;
- ; ; now give some time to old jerky vga cards
- ; jc zik
- ; zik:
- ; jnc zok
- ; zok:
- ; jc zik2
- ; zik2:
- ; jnc zok2
- ; zok2:
- ; jc zik3
- ; zik3:
- ; jnc zok3
- ; zok3:
-
- out dx,al
- sti
-
- ret
-
- ;--------------------------------------------------------------------------
- ; void cdecl PageFlip(void)
- ;
- public _PageFlip
-
- _PageFlip: ; _Viewbase <-- _ActiveBase <-- MidBase <-- _ViewBase
- ; & show new _ViewBase
- pushad
- mov ebx,PageTicks
- @pfgloop:
- mov eax,_TimerTicks
- mov edx,eax
- sub eax,ebx
- cmp eax,FrameTicks
- jb @pfgloop ; loop if too few time has passed
- mov PageTicks,edx
-
- mov eax,MidBase
- mov ebx,_ViewBase
- mov ecx,_ActiveBase
- mov _ActiveBase,eax
- mov MidBase,ebx
- mov _ViewBase,ecx
- ; ecx == new viewbase
- call DisplayPage
- popad
- ret
-
- ;--------------------------------------------------------------------------
- ; void cdecl SplitScreen(ecx = Splitline)
- ; INTERNAL FUNCTION
-
- SplitScreen:
- ; ecx = SplitLine (in low word)
-
- ; inanzitutto disabilita il panning
- ; dello splitscreen, ma prima salva il parametro
- push ecx
- cli
-
- mov dx,STATUS ;poni attribute controller in address mode
- in al,dx
-
- mov ecx,200
- okuto1: loop okuto1
-
- ; ora disabilita il panning dello splitscreen
- mov al,ATTR_CONTROL
- mov dx,ATTRIBUTE
- out dx,al ; seleziona registro di panning
-
- ; lascia passare del tempo
- mov ecx,200
- okuto2: loop okuto2
-
- inc dx
- in al,dx ;leggi gli attributi correnti
- or al,NOSPLITPAN
-
- ; lascia passare del tempo
- mov ecx,200
- okuto3: loop okuto3
-
- mov ah,al ; salva i flag
-
- mov dx,STATUS ;
- in al,dx ; nuovamente in address mode (ripulisci il f/f di stato)
-
- mov dx,ATTRIBUTE
- mov al,ATTR_CONTROL ;pronto a ri-scrivere su attribute controller
- out dx,al
-
- ; lascia passare del tempo
- mov ecx,200
- okuto4: loop okuto4
-
- mov al,ah ; scrivi i nuovi flag degli attributi video
- out dx,al ;
-
- sti
-
- ; ora puoi modificare il line compare
- ; register e gli altri suoi bits
- ; sparsi in altri 2 registri
- pop ecx
- ; Now wait for vertical sync, so the other page will be invisible when
- ; we start drawing to it.
- mov dx,STATUS
- cli
- @@WVS:
- in al,dx
- and al,08h
- jz @@WVS ;vertical sync is active high (1 = active)
-
- mov dx,CRTC
-
- ; ECX = splitline
-
- shl ecx,1 ; moltiplica per due
- ; (si e' in modo a doppia scansione)
- dec ecx ; e riduci di 1
-
- ; write bit 0..7
- mov al,LINE_COMPARE
- mov ah,cl
- out dx,ax
-
- ; write bit 8
-
- mov cl,0
-
- shr ecx,1 ; porta il bit 8
- shr cl,3 ; nel bit 4 di BL
-
- mov ax,0707h ;bit 8 is CRTC INDEX 7 BIT 4
- out dx,al
- inc dx
- in al,dx
- dec dx
- and al,0EFh ;azzera bit 4
- or al,cl ; registra il nuovo bit
- xchg ah,al
- out dx,ax
-
- ; write bit 9
- mov cl,0
- shr ecx,1
- shr cl,1
- mov ax,0909h
- out dx,al
- inc dx
- in al,dx
- dec dx
- and al,0BFh ;azzera bit 6
- or al,cl
- xchg al,ah
- out dx,ax
-
- sti ;enable interrupts
- ret
-
- ; EXTENDED INPUT, TIMER DRIVEN PAGE FLIPPING & SOUND OUTPUT
- ; questa sezione di 386VIDEO(game)
- ; gestisce in modo diretto la tastiera,lo speaker incorporato
- ; in ogni PC & il timer connesso a IRQ0.
-
-
- ; RAW KEYBOARD I/O
- ; 32bit section, Keyboard ISR for raw keyboard input
-
- ; Raw KeyBoard table
- ; Every key "description" is made of two consecutive bytes
- ; if a key has a keyboard scancode K
- ; address:
- ; _RKB+(K) bit meaning: description:
- ; 0 IS_PRESSED 0 == key K is currently not pressed
- ; 1 == key K is currently pressed
- ;
- ; 1 TOUCHED 0 == key K has not been pressed
- ; since last time you cleared this bit.
- ; 1 == key K has been pressed
- ;
- ; Use IS_PRESSED for "raw" control (i.e cursor keys in a game)
- ; and TOUCHED (but clear it before!!) for "keyboard-like" control
- ; when you have to choose items in a menu or when
- ; you have to check special "toggle" keys that may be pressed anytime
- ; (i.e. the all time high ESC key)
- public _RKB,_RKBPressed
- _RKB db 0
- db 128 dup(0)
-
- _RKBPressed db 0 ; 0 == no keys pressed since last time you reset this flag
- ; 1 == something happened, a key has been pressed
- ; (this is like a "general" TOUCHED flag)
-
- IRQ1_ISR:
- cli
- push eax
- push ebx
- push ds
- mov ds,cs:_SelData
-
- in al,60h ; get scan code
-
- movzx ebx,al ; move scan code to index register
-
- in al,61h ; get control code
- push eax
- or al,80h ; clear keyboard of interrupt:
- out 61h,al ;
- pop eax ; first send control byte with inverted MSB
- out 61h,al ; then send plain control byte
-
- mov al,EOI ; send generic EOI to
- out PIC0_CTRL,al ; PIC
- ; enabling other interrupts
- mov al,bl
- and bl,07Fh
- ; if the key was released, the high bit is set in the scan code
- mov byte ptr[ebx+offset _RKB],02h ; reset "Is being pressed" flag
- ; and left set "Has been pressed"
-
- rol al,1
- jc key_released
- mov byte ptr [ebx+offset _RKB],03h ; set "Is being pressed" flag
- ; and "Has been pressed" flag
- key_released:
- mov _RKBPressed,1 ; state of keyboard has changed
- sti
- pop ds
- pop ebx
- pop eax
- iretd
-
- public _WaitKey
- _WaitKey:
- ; WAITS UNTIL A KEY IS PRESSED
- mov _RKBPressed,0
- @waitmore:
- test _RKBPressed,1
- jz @waitmore
- ret
-
- public _InstallRKB
- _InstallRKB:
- pushad
- mov eax,0
- mov edi,offset _RKB
- mov ecx,32 ; 128bytes == 32 dwords
- rep stosd
- cli
- test _386Man,IS_DPMI
- jnz NoReflex
- mov al,21h
- mov V86ax,2509h
- mov V86ds,seg code16
- mov V86dx,offset IRQ1_RISR
- int 33h
- NoReflex:
- mov bl,1
- mov edx,offset IRQ1_ISR
- call _SetIRQ
- sti
- popad
- ret
-
- ; PWM SOUND ON PC-SPEAKER & TIMER-DRIVEN PAGE FLIPPING
- ; 32bit section
-
- public _SoundOn,_SoundLen,_SoundPtr
- public _DSoundOn,_DSoundLen,_DSoundPtr
-
- align dword
- ; current sound data
- _SoundLen dd 0 ; default = zero sound lenght
- _SoundPtr dd 0 ; default = null, points to already decode sound data
- ; the installed sound driver must play
- ; default sound data
- _DSoundLen dd 0 ; default = zero , default sound lenght
- _DSoundPtr dd 0 ; default = null , default sound
-
- align byte
-
- _SoundOn db 0 ; Set this to turn on sound generation, all sound driver must
- ; refer to this flag to control sound output
- _DSoundOn db 0 ;ditto for the default sound insertion at end of sound
-
-
- Buzzing db 0 ; are we currently producing sound ? (private var.)
-
- align dword
- ; decrementi di contatore usati come riferimento
- PWMTICK = 149 ; conteggio equivalente a 8008Hz
- VSyncTick dd 0 ; Vsync count ... Initialize with VSyncInit()
- TIMERTICK = (64*1024) ; conteggio equivalente a 18.2 Hz
- ONESECOND = 1193180
-
- public _TimerTicks,_SysTicks,_Seconds
-
- _TimerTicks dd 0 ; ticks in frequenza base a 1193180 Hz
- ; usa sempre la granularita piu fine a disposizione
-
- PageTicks dd 0 ; tick counter for pageflips
- FrameTicks = 19886 ; 1193180hz/60hz timer count
-
- InnerTicks dd 0 ; simile a _TimerTicks, ma usato per calcolare systicks
- SecTicks dd 0 ; idem, ma per _Seconds
-
- _SysTicks dd 0 ; ticks a 18.2Hz
- _Seconds dd 0 ; contasecondi totali
-
- align byte
-
- InstallPFLP:
- ; installs the pageflip support code
- pushad
- cli
- ; first in real mode
- test _386Man,IS_DPMI
- jnz @nopfreflex
- mov al,21h
- mov V86ax,2508h
- mov V86ds,code16
- mov V86dx,offset PFLP_RISR
- int 33h
- @nopfreflex:
- ; second in protected mode (it works only this way under DPMI)
- mov bl,0
- mov edx,offset PFLP_ISR
- call _SetIRQ
- mov al,T_SET0 ; set programmable interval timer 0 to FrameTicks
- out PIT_CTRL,al ;
- mov eax,FrameTicks
- out PIT0,al ;
- mov al,ah ;
- out PIT0,al ;
- ; initialize counters
- mov _TimerTicks,0
- mov PageTicks,0
- mov InnerTicks,0
- mov SecTicks,0
- mov _SysTicks,0
- mov _Seconds,0
- sti
- popad
- ret
-
- PFLP_ISR:
- sti
- push eax
- push ebx
- push ds
-
- mov ds,cs:_SelData
- mov ebx,FrameTicks
- add _TimerTicks,ebx
- add InnerTicks,ebx
- add SecTicks,ebx
- mov eax,SecTicks
- sub eax,ONESECOND
- jb pdone_sec
- mov SecTicks,eax
- inc _Seconds
- pdone_sec:
-
- mov eax,InnerTicks
- sub eax,TIMERTICK
- jb pdone_irq0
- mov InnerTicks,eax
- ; n.b. TTick conta i ticks di sistema in formato fixed point
- ; con una cifra decimale
- inc _SysTicks
- pzapped_time:
- ; it's time to call the old ISR
- mov al,8
- int 33h
- jmp short pirq0_digged
- pdone_irq0:
- mov al,EOI
- out PIC0_CTRL,al
- pirq0_digged:
- pop ds
- pop ebx
- pop eax
- iretd ; ritorna il controllo a 386 power
-
- public _InstallPWM
- _InstallPWM:
- ; install irqs & set up voc_table
- pushad
- ; initialize internal vars
- mov Buzzing,0
- mov _SoundOn,0
- mov _DSoundOn,0
- mov _SoundLen,0
- mov _SoundPtr,0
- mov _DSoundLen,0
- mov _DSoundPtr,0
- ; set voc_table
- mov esi,offset pwm_table
- mov edi,offset voc_table
- mov eax,0
- mov ecx,64
- set_up_voc_table:
- movsd
- loop set_up_voc_table
- cli
- ; first install the real mode side
- cmp _386Man,IS_DPMI
- je @nopwreflex
- mov al,21h
- mov V86ax,2508h
- mov V86ds,code16
- mov V86dx,offset code16:IRQ0_RISR
- int 33h
- @nopwreflex:
- ; then the protected mode side (it works only this way in DPMI)
- mov bl,0
- mov edx,offset IRQ0_ISR
- call _SetIRQ
- mov ebx,F8008 ; 8008Hz count
- cmp _386Man,IS_DPMI
- jne @vcpispeed
- shl ebx,1 ; freq to 4004Hz
- @vcpispeed:
- mov play_rate,ebx ; set playback frequency for voc converter
-
- mov al,T_SET0 ; set programmable interval timer 0 to 8008Hz or 4004Hz
- out PIT_CTRL,al ;
- mov al,bl ;
- out PIT0,al ;
- mov al,bh ;
- out PIT0,al ;
-
- sti
- ; no need to initialize time counters
- ; InstallPFLP already did it
- popad
- ret
-
- ; PWM SOUND SPEAKER DRIVER
-
- zarp_sound:
- cmp _DSoundOn,0
- je dont_buzz
- mov eax,_DSoundLen
- dec eax
- mov ebx,_DSoundPtr
- mov _SoundLen,eax
- jmp doit_again
-
- dont_buzz:
- cmp Buzzing,0
- je getoutsound
- mov Buzzing,0
- ; turn speaker OFF
- in al, 61h ;Read I/O port B into AL
- and al, 11111100b ;mask lower two bits
- out 61h, al ;to turn off speaker
- jmp short getoutsound
-
- DoTheSound macro
- cmp _SoundOn,0
- je dont_buzz ; no sound if sound flag is off
- cmp _SoundLen,0
- je zarp_sound ; no sound if at end of "soundtrack"
- dec _SoundLen ; decrease "soundtrack" lenght
-
- mov ebx,_SoundPtr ;get current count pointer
- doit_again:
- mov al,[ebx] ; count into AX
- inc ebx ; & update sound pointer
- mov _SoundPtr,ebx ; (only offset is changed)
- mov ah,al ; copy count
- or al,al ; zero count sets speaker off
- ;je dont_buzz ;
-
- mov al,P_SET2S
- out PIT_CTRL,al
- mov al,ah
- out PIT2, al
-
- cmp Buzzing,0
- jne getoutsound
- mov Buzzing,1
- ; turn sound on
- in al, 61h ;read I/O port B into AL
- or al,3 ;turn on bits 0 and 1
- out 61h,al ;to turn on speaker
- getoutsound:
- endm
-
- ; IRQ0 Timer handler, it handles TWO different "time driven" nested loops
- ; the 8008 Hz PWM sound system
- ; the 18,2 Hz System tick for periodic events and rough time keeping
-
- IRQ0_ISR:
- cli
- push eax
- push ebx
- push ecx
- push edx
- push ds
-
- mov ds,cs:_SelData
- mov ebx,play_rate
- add _TimerTicks,ebx
- add InnerTicks,ebx
- add SecTicks,ebx
- DoTheSound
- sti
- mov eax,SecTicks
- sub eax,ONESECOND
- jb done_sec
- mov SecTicks,eax
- inc _Seconds
- done_sec:
-
- mov eax,InnerTicks
- sub eax,TIMERTICK
- jb done_irq0
- mov InnerTicks,eax
- ; n.b. TTick conta i ticks di sistema in formato fixed point
- ; con una cifra decimale
- inc _SysTicks
- zapped_time:
- ; it's time to call the old ISR
- mov al,8
- int 33h
- jmp short irq0_digged
- done_irq0:
- mov al,EOI
- out PIC0_CTRL,al
- irq0_digged:
- pop ds
- pop edx
- pop ecx
- pop ebx
- pop eax
- iretd ; ritorna il controllo a 386 power
-
- ;-----------------------------------------------------------------------------
- ; 8bit, not compressed VOC to "raw 8 bit pcm"
- align dword
- voc_rate dd ?
- play_rate dd ? ; playback sample rate and IRQ0 frequency under PWM sound
-
- align byte
- pwm_table db 1 , 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20
- db 21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30
- db 31,31,31,32,32,32,33,33,33,34,34,34,35,35,35,36,36,36,37,37
- db 37,38,38,38,39,39,39,40,40,40,41,41,41,42,42,42,43,43,43,44
- db 45,45,45,46,46,46,47,47,47,48,48,48,49,49,49,50,50,50,51,51
- db 51,52,52,52,53,53,53,54,54,54,55,55,55,56,56,56,57,57,57,57
- db 58,58,58,58,59,59,59,59,60,60,60,60,61,61,61,61,62,62,62,62
- db 63,63,63,63,63,64,64,64,64,64,65,65,65,65,65,66,66,66,66,66
- db 67,67,67,67,67,68,68,68,68,68,69,69,69,69,69,70,70,70,70,70
- db 71,71,71,71,71,71,71,71,71,71,72,72,72,72,72,72,72,72,72,72
- db 73,73,73,73,73,73,73,73,73,73,74,74,74,74,74,74,74,74,74,74
- db 75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75
- db 75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75
-
- voc_table db 1 , 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20
- db 21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30
- db 31,31,31,32,32,32,33,33,33,34,34,34,35,35,35,36,36,36,37,37
- db 37,38,38,38,39,39,39,40,40,40,41,41,41,42,42,42,43,43,43,44
- db 45,45,45,46,46,46,47,47,47,48,48,48,49,49,49,50,50,50,51,51
- db 51,52,52,52,53,53,53,54,54,54,55,55,55,56,56,56,57,57,57,57
- db 58,58,58,58,59,59,59,59,60,60,60,60,61,61,61,61,62,62,62,62
- db 63,63,63,63,63,64,64,64,64,64,65,65,65,65,65,66,66,66,66,66
- db 67,67,67,67,67,68,68,68,68,68,69,69,69,69,69,70,70,70,70,70
- db 71,71,71,71,71,71,71,71,71,71,72,72,72,72,72,72,72,72,72,72
- db 73,73,73,73,73,73,73,73,73,73,74,74,74,74,74,74,74,74,74,74
- db 75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75
- db 75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75
-
- set_comp macro
- lodsb
- or al,al
- mov al,2 ; compressed data
- jne voc_end
- endm
-
- set_sample macro
- lodsb
- and eax,0FFh
- mov ebx,256
- mov edx,0
- mov eax,1000000
- div ebx
- ; eax = samples/sec
- mov ebx,eax
- mov edx,0
- mov eax,1193180
- div ebx
- ; eax = timer count equivalent to sample rate
- mov voc_rate,eax
- endm
-
- blitquiet macro
- ; ecx =ctr
- mov edx,0
- mov ebx,voc_rate
- mov ebp,play_rate
- mov eax,0
- stamp:
- dec ecx
- je end_sil
- add edx,ebx
- cmp edx,ebp
- jb stamp
- sub edx,ebp
- stosb
- jmp stamp
- end_sil:
- endm
-
- blitsound macro
- ; ecx = ctr
- mov edx,0
- zound: mov ebx,0
- mov eax,0
- interp: add al,[esi]
- adc ah,0
- inc esi
- inc ebx
- dec ecx
- je end_data
- add edx,voc_rate
- cmp edx,play_rate
- jb interp
- end_data: sub edx,play_rate
- div bl
- mov al,[eax + voc_table]
- stosb
- cmp ecx,0
- jne zound
- endm
-
-
- VocPackets dd offset voc_end, offset voc_data, offset voc_cont
- dd offset quiet, offset marker, offset ascii
- dd offset rep_start, offset rep_end, offset extend
- decoder: mov ebx,0
- decode: lodsd
- mov bl,al
- cmp al,9
- jnb voc_end
- jmp [ebx*4+ VocPackets]
-
- rep_end: mov al,1 ; rep end without rep_start if it is not matched
- voc_end: ret
-
- rep_start:
- lodsw
- push esi ; inserisci puntatore
- reploop:
- mov esi,[esp] ; ricarica puntatore
- push eax
- call decode
- pop eax
- dec ax
- jne reploop
- add esp,4 ; rimuovi puntatore
- jmp decode
-
- voc_data:
- mov ecx,-2
- shr eax,8
- add ecx,eax
- set_sample
- set_comp
- sblit:
- blitsound
- jmp decoder
-
- voc_cont:
- shr eax,8
- mov ecx,eax
- jmp sblit
-
- quiet:
- movzx eax, word ptr [esi]
- mov ecx,1
- add esi,2
- add ecx,eax
- set_sample
- blitquiet
- jmp decoder
-
- extend: mov al,3 ; extended voc file
- ret
-
- marker:
- add esi,2
- jmp decode
-
- ascii:
- shr eax,8
- add esi,eax
- jmp decode
-
- vocstamp db 'Creative Voice File',1Ah
-
- public _Voc2RAW
- _Voc2RAW:
- ; in:
- ; esi = .VOC data to translate, edi = destination for RAW data
- ; al = error code (0 == no errors)
- ; ebx = RAW datablock
- ; edi = end of RAW datablock + 1
- push edi ; save data start
- add edi,4
- movzx ebx,word ptr [esi+14h]
- mov edx,esi
- mov ecx,0
- add esi,ebx
- mov ebx, offset vocstamp
- votest: mov eax,[edx]
- cmp eax,[ebx]
- jne eend
- add edx,4
- add ebx,4
- inc ecx
- jmp votest
- eend: cmp ecx,5
- jne novoc
- call decoder
- pop ebx ; restore data start
- sub edi,ebx
- sub edi,4
- mov [ebx],edi
- ; al is zero (value transmitted from decoder)
- ret
- novoc:
- add esp,4 ; remove pointer to start of voc file
- mov al,4 ; not a voc file
- ret
-
- code32 ends
-
- code16 segment para public use16
- assume cs:code16,ds:code32
- ; here comes the 16-bit handlers for irq0 and irq1
- ; (to support bimodal irqs without wasteful callbacks)
-
- ; RAW KEYBOARD
- ; 16bit section, Keyboard ISR for raw keyboard input
-
- IRQ1_RISR: ;Real mode ISR
- ; WARNING! BE SURE 386Video IS LINKED IMMEDIATLY AFTER
- ; 386Power (to be sure all the var accessed are into a 64k range)
- ; OR STRANGE THINGS MAY HAPPEN!!!!!!!
- ; (depending on what assembler you use to assemble this stuff)
- push eax
- push ebx
- push ds
- mov ax,seg code32
- mov ds,ax
-
- in al,60h ; get scan code
-
- movzx ebx,al ; move scan code to index register
-
- in al,61h ; get control code
- push eax
- or al,80h ; clear keyboard of interrupt:
- out 61h,al ;
- pop eax ; first send control byte with inverted MSB
- out 61h,al ; then send plain control byte
-
- mov al,EOI ; send generic EOI to
-
- out PIC0_CTRL,al ; PIC
- ; enabling other interrupts
- mov al,bl
- and bl,07Fh ; remove flag bit
- ; if the key was released, the high bit is set in the scan code
- mov byte ptr ds:[ebx+offset _RKB],02h ; reset "Is being pressed" flag
- ; and left set "Has been pressed"
-
- rol al,1 ;
- jc rkey_released ;
- mov byte ptr ds:[ebx+offset _RKB],03h ; set "Is being pressed" flag
- ; and "Has been pressed" flag
- rkey_released:
- mov ds:_RKBPressed,1 ; state of keyboard has changed
- pop ds
- pop ebx
- pop eax
- iret
-
- ; PWM SOUND SPEAKER DRIVER
-
- rdont_buzz:
- cmp Buzzing,0
- je rgetoutsound
- mov Buzzing,0
- ; turn speaker OFF
- in al, 61h ;Read I/O port B into AL
- and al, 11111100b ;mask lower two bits
- out 61h, al ;to turn off speaker
- jmp rgetoutsound
-
- RDoTheSound macro
- cmp _SoundOn,0
- je rdont_buzz ; no sound if sound flag is off
- cmp _SoundLen,0
- je rdont_buzz ; no sound if at end of "soundtrack"
- dec _SoundLen ; decrease "soundtrack" lenght
-
- mov ebx,_SoundPtr ;get current count pointer
- inc _SoundPtr ; increase pointer
- mov eax,ebx
- shr ebx,4
- and ax,0Fh
- add bx,seg code32
- mov es,bx
- mov al,es:[ebx] ; count into AX
-
- or al,al ; zero count sets speaker off
- ;je rdont_buzz ;
- mov ah,al ;
-
- mov al,P_SET2S
- out PIT_CTRL,al
-
-
- mov al,ah
- out PIT2, al
-
- cmp Buzzing,0
- jne rgetoutsound
- mov Buzzing,1
- ; turn sound on
- in al, 61h ;read I/O port B into AL
- or al,3 ;turn on bits 0 and 1
- out 61h,al ;to turn on speaker
- rgetoutsound:
- endm
-
- ; IRQ0 Timer handler, it handles TWO different "time driven" nested loops
- ; the 8008 Hz PWM sound sytem
- ; the 18,2 Hz System tick for periodic events and rough time keeping
-
- IRQ0_RISR:
- push eax
- push ebx
- push ecx
- push edx
- push ds
- push es
- mov ax,code32
- mov ds,ax
- mov ebx,play_rate
- add _TimerTicks,ebx
- add InnerTicks,ebx
- add SecTicks,ebx
- RDoTheSound
- sti
- mov eax,SecTicks
- sub eax,TIMERTICK
- jb rdone_sec
- mov SecTicks,eax
- inc _Seconds
- rdone_sec:
-
- mov eax,InnerTicks
- sub eax,TIMERTICK
- jb rdone_irq0
- mov InnerTicks,eax
- ; n.b. TTick conta i ticks di sistema in formato fixed point
- ; con una cifra decimale
- inc _SysTicks
- rzapped_time:
- ; it's time to call the old ISR
- pushf
- call dword ptr cs:[(8*4) + offset _OldInt]
- jmp short rirq0_digged
- rdone_irq0:
- mov al,EOI
- out PIC0_CTRL,al
- rirq0_digged:
- pop es
- pop ds
- pop edx
- pop ecx
- pop ebx
- pop eax
- iret ; ritorna il controllo a 386 power
-
- PFLP_RISR:
- push eax
- push ebx
- push ds
- mov ax,code32
- mov ds,ax
- mov ebx,FrameTicks
- add _TimerTicks,ebx
- add InnerTicks,ebx
- add SecTicks,ebx
- sti
- mov eax,SecTicks
- sub eax,ONESECOND
- jb prdone_sec
- mov SecTicks,eax
- inc _Seconds
- prdone_sec:
-
- mov eax,InnerTicks
- sub eax,TIMERTICK
- jb prdone_irq0
- mov InnerTicks,eax
- ; n.b. TTick conta i ticks di sistema in formato fixed point
- ; con una cifra decimale
- inc _SysTicks
- przapped_time:
- ; it's time to call the old ISR
- pushf
- call dword ptr cs:[(8*4) + offset _OldInt]
- jmp short prirq0_digged
- prdone_irq0:
- mov al,EOI
- out PIC0_CTRL,al
- prirq0_digged:
- pop ds
- pop ebx
- pop eax
- iret ; ritorna il controllo a 386 power
-
- code16 ends
-
- END
-